package com.book.oauth.server.user.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.book.common.api.oauth.CacheKey;
import com.book.common.util.GuavaCacheUtil;
import com.book.oauth.config.ResourceServerConfig;
import com.book.oauth.server.role.entity.AuthRole;
import com.book.oauth.server.role.entity.Role;
import com.book.oauth.server.role.service.IRoleService;
import com.book.oauth.server.user.entity.AuthUser;
import com.book.oauth.server.user.entity.User;
import com.book.oauth.server.user.entity.UserRole;
import com.book.oauth.server.user.service.IUserRoleService;
import com.book.oauth.server.user.service.IUserService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Description： 重写用户验证方法
 *
 * @Author： leo.xiong
 * @CreateDate： 2019/10/11 17:11
 * @Email： leo.xiong@suyun360.com
 * Version：1.0
 */
@Slf4j
@DS(value = "oauth")
@Service(value = "userDetailServiceImpl")
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private IUserService userService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IUserRoleService userRoleService;

    @Autowired
    private IRoleService roleService;

    @Override
    public UserDetails loadUserByUsername(String loginName) throws UsernameNotFoundException {
        AuthUser authUser = GuavaCacheUtil.get(CacheKey.OAUTH_LOGIN_NAME + loginName, AuthUser.class);
        if (authUser != null) {
            return authUser;
        }
        User user = new User();
        user.setUsername(loginName);
        user = userService.getOne(Wrappers.query(user));
        if (user == null) {
            throw new RuntimeException("BOOK:CORE:10009");
        }
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        authUser = new AuthUser();
        BeanUtils.copyProperties(user, authUser);
        authUser.setId(user.getId().toString());
        userService.buildCurrentUserInfo(authUser);
        List<UserRole> userRoleList = userRoleService.findAllList(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, user.getId()));
        if (CollectionUtils.isEmpty(userRoleList)) {
            GuavaCacheUtil.put(CacheKey.OAUTH_LOGIN_NAME + loginName, authUser);
            return authUser;
        }
        List<Long> roleIdList = userRoleList.parallelStream().map(UserRole::getRoleId).collect(Collectors.toList());
        List<Role> roleList = roleService.findAllList(new LambdaQueryWrapper<Role>().in(Role::getId, roleIdList));
        if (CollectionUtils.isEmpty(roleIdList)) {
            GuavaCacheUtil.put(CacheKey.OAUTH_LOGIN_NAME + loginName, authUser);
            return authUser;
        }
        for (Role role : roleList) {
            AuthRole authRole = new AuthRole();
            authRole.setRoleName(ResourceServerConfig.ROLE_PREFIX + role.getEnName().toUpperCase());
            authUser.getAuthorities().add(authRole);
        }
        //如果路径角色不存在，默认给一个普通角色
        if (CollectionUtils.isEmpty(authUser.getAuthorities())) {
            AuthRole authRole = new AuthRole();
            authRole.setRoleName(ResourceServerConfig.ROLE_PREFIX + ResourceServerConfig.USER);
            authUser.getAuthorities().add(authRole);
        }
        GuavaCacheUtil.put(CacheKey.OAUTH_LOGIN_NAME + loginName, authUser);
        return authUser;
    }
}
